package com.ailk.cuc.autotestbg.startup;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.logging.Log;

import com.ailk.cuc.autotestbg.common.bean.AutoCaseStepBGBean;
import com.ailk.cuc.autotestbg.common.bean.AutoHostInfoBGBean;
import com.ailk.cuc.autotestbg.common.bean.AutoTestCaseBean;
import com.ailk.cuc.autotestbg.common.bean.AutoTestPlanBean;
import com.ailk.cuc.autotestbg.common.bean.AutoTestPlanTestCaseBean;
import com.ailk.cuc.autotestbg.common.business.interf.BusinessProcessInterface;
import com.ailk.cuc.autotestbg.common.constants.StaticParam;
import com.ailk.cuc.autotestbg.common.utils.BusiProcesserFactory;
import com.ailk.cuc.autotestbg.common.utils.LogUtils;
import com.ailk.cuc.autotestbg.common.utils.SpringContextUtil;
import com.ailk.cuc.autotestbg.xml.bean.AutoEssDataBean;
import com.ailk.cuc.autotestbg.xml.bean.AutoEssInterfaceBean;
import com.ailk.cuc.autotestbg.xml.constants.EssEcsConstants;
import com.ibatis.sqlmap.client.SqlMapClient;


public class SocketProcesser implements Runnable{

	private Socket socket;

	private static Log logger = LogUtils.getLogger(SocketProcesser.class.getName());
	public void run() {
		logger.info("开始处理客户端连接");
		clientProcesser();
	}
	
	private void clientProcesser(){
		BufferedInputStream in = null;
		BufferedOutputStream out = null;
		Map<String,Object> argMap = new HashMap<String,Object>();
		
		try {
			in = new BufferedInputStream(socket.getInputStream());
			out = new BufferedOutputStream(socket.getOutputStream());
			
			parserMsg(in,argMap);
			
			checkPlan(argMap);
			
			responseWeb(out,argMap);
			
			System.out.println(logger.getClass().getCanonicalName());
			logger.info("msgTransOk: "+argMap.get("msgTransOk"));
			logger.info("planOk: "+argMap.get("planOk"));
			logger.info("caseOk: "+argMap.get("caseOk"));
			if((Boolean)argMap.get("msgTransOk") && (Boolean)argMap.get("planOk") && (Boolean)argMap.get("caseOk")){
				logger.info("开始处理业务逻辑");
				//根据不同的计划类型，调用不同的业务处理器
				BusinessProcessInterface busiProcesser = null;
				String interfaceType = null;
				if("1".equals(argMap.get("interfaceType").toString())){
					interfaceType = EssEcsConstants.XML_BUSI_PROCESSER_TYPE_ESS;
				}else{
					interfaceType = EssEcsConstants.XML_BUSI_PROCESSER_TYPE_ECS;
				}
				
				busiProcesser = BusiProcesserFactory.getBusiProcesser(interfaceType);
				busiProcesser.processBusi(argMap);
			}
			
		} catch (IOException e) {
			logger.error("客户端处理异常");
			logger.error(e.getMessage());
		}finally{
			try {
				in.close();
				out.close();
				socket.close();
			} catch (IOException e) {
				logger.error("关闭资源异常");
				logger.error(e.getMessage());
			}
		}
	}
	
	public void parserMsg(InputStream in,Map<String,Object> argMap){
		long taskId = 0;
		long testPlanId = 0;
		int planType = 0;
		boolean msgTransOk = true;
		byte[] bin = new byte[StaticParam.fieldMsgLength];
		int readedLen = 0;
		String returnMsg = "";
		
		try {
			while(readedLen < bin.length) {
				readedLen += in.read(bin, readedLen, bin.length-readedLen);
			}
			
			int msgLen = Integer.parseInt(new String(bin));
			bin = new byte[msgLen];
			readedLen = 0;
			
			while(readedLen < bin.length) {
				readedLen += in.read(bin, readedLen, bin.length-readedLen);
			}
			
			String msg = new String(bin);
			
			String[] temp = msg.split("\\|");
			
			taskId = Long.parseLong(temp[0].trim());
			testPlanId = Long.parseLong(temp[1].trim());
			planType = Integer.parseInt(temp[2].trim());
		} catch (Exception e) {
			logger.error("[报文接收解析过程发生异常]");
			logger.error(e.getMessage());
			returnMsg = "[报文接收解析过程发生异常: " + e.getMessage() + "]";
			msgTransOk = false;
		} 
		
		argMap.put("taskId", taskId);
		argMap.put("planId", testPlanId);
		argMap.put("planType", planType);
		argMap.put("returnMsg", returnMsg);
		argMap.put("msgTransOk", msgTransOk);
		logger.info("[报文接收解析完毕]");
	}
	
	@SuppressWarnings({ "unchecked", "null" })
	public void checkPlan(Map<String,Object> argMap){
		String returnMsg = (String)argMap.get("returnMsg");
		AutoTestPlanBean planBean = null;
		boolean planOk = true;
		boolean caseOk = true;
		SqlMapClient sqlMapClient = (SqlMapClient) SpringContextUtil.getBean("sqlMapClient");
		
		try {
			planBean = (AutoTestPlanBean)sqlMapClient.queryForObject("common_init.getTestPlanBean", argMap);
			ArrayList<AutoTestPlanTestCaseBean> testPlanTestCaseList = null;
			ArrayList<AutoCaseStepBGBean> caseStepBGList = null;
			
			if(planBean != null){
				planBean.setTaskId((Long)argMap.get("taskId"));
				testPlanTestCaseList =  (ArrayList<AutoTestPlanTestCaseBean>)sqlMapClient.queryForList("common_init.getPlanCaseList", argMap);
				
				if(testPlanTestCaseList != null && testPlanTestCaseList.size() != 0){
					planBean.setPlanCaseList(testPlanTestCaseList);
					
					for(AutoTestPlanTestCaseBean testPlanTestCase : testPlanTestCaseList){
						String testCaseId = testPlanTestCase.getTestCaseId()+"";
						
						AutoTestCaseBean testCaseBean = (AutoTestCaseBean)sqlMapClient.queryForObject("common_init.getTestCaseBean", testCaseId);
						testPlanTestCase.setTestCaseBean(testCaseBean);
						
						caseStepBGList = (ArrayList<AutoCaseStepBGBean>)sqlMapClient.queryForList("common_init.getCaseStepBGList", testCaseId);
						testCaseBean.setCaseStepList(caseStepBGList);
						
						if(caseStepBGList == null || caseStepBGList.size() == 0){
							caseOk = false;
							returnMsg += "[测试用例" + testCaseId + "下没有测试步骤,请给该测试用例添加测试步骤]";
						}else{
							//此处用来判断计划是哪种类型（全业务，ESS）
							AutoCaseStepBGBean caseStepBGBean = caseStepBGList.get(0);
							String dataId = caseStepBGBean.getInputDataId()+"";
							AutoEssDataBean essDataBean = (AutoEssDataBean)sqlMapClient.queryForObject("xml_ess_ecs_assembly.getEssDatabean", dataId);
							AutoEssInterfaceBean interfaceBean = (AutoEssInterfaceBean)sqlMapClient.queryForObject("xml_ess_ecs_assembly.getEssInterfaceBean", essDataBean);
							
							argMap.put("interfaceType", interfaceBean.getInterfacetype());
						}
						
						AutoHostInfoBGBean hostInfoBGbean = (AutoHostInfoBGBean)sqlMapClient.queryForObject("common_init.getHostInfoBGBean",testCaseBean.getHostId()+"");
						testCaseBean.setHostInfoBean(hostInfoBGbean);
					}
					if(caseOk){
						returnMsg = "测试计划" + planBean.getPlanId() + "解析完毕,进入测试计划脚本生成阶段!";
					}
				}else{
					planOk = false;
					returnMsg += "[测试计划" + planBean.getPlanId() + "下没有测试用例,请给该测试计划添加测试用例后再进行测试]";
				}
			}else{
				planOk = false;
				returnMsg += "[测试计划" + planBean.getPlanId() + "在数据库中无定义,请检查数据库中配置数据是否有问题]" ;
			}
			
			
		} catch (SQLException e) {
			planOk = false;
			caseOk = false;
			returnMsg += "[测试计划" + argMap.get("planId") + "没有验证通过]" ;
			logger.error("[测试计划" + argMap.get("planId") + "没有验证通过]");
		}
		
		argMap.put("planOk", planOk);
		argMap.put("caseOk", caseOk);
		argMap.put("returnMsg", returnMsg);
		argMap.put("planBean", planBean);
		logger.info("[测试计划" + argMap.get("planId") + "验证通过]");
	}
	
	public void responseWeb(OutputStream out,Map<String,Object> argMap){
		String returnMsg = (String)argMap.get("returnMsg");
		String outLength = Integer.toString(returnMsg.getBytes().length);
		while (outLength.length()<StaticParam.fieldMsgLength) {
			outLength = "0" + outLength;
		}

		byte[] bin = (outLength + returnMsg).getBytes();
		logger.info("回复WEB端报文信息:" + outLength + returnMsg);
		try {
			out.write(bin,0,bin.length);
			out.flush();
		} catch (IOException e) {
			logger.error("发送回WEB端时，发生异常");
			logger.error(e.getMessage());
		}
		logger.info("回复WEB端成功");
	}

	public Socket getSocket() {
		return socket;
	}

	public void setSocket(Socket socket) {
		this.socket = socket;
	}

	public SocketProcesser(Socket socket) {
		super();
		this.socket = socket;
	}

	public SocketProcesser() {
		super();
	}
	
}
